# -*- coding: utf-8 -*-
# created on 2016/5/5

from mathsolver.functions.base import *
from mathsolver.functions.yuan.base import Yuan, peifang, default_symbols
from sympy import degree, simplify, pi
from mathsolver.functions.budengshi import common_opers


# 判断是否是二元二次方程: Ax^2+By^2+Cxy+Dx+Ey+F=0
class ErYuanErCiJudge(BaseFunction):
    def solver(self, *args):
        answer = False
        eq = args[0].sympify()
        expr = (eq[0] - eq[1]).expand().simplify()
        symx, symy = default_symbols(expr)
        if expr.is_Add:
            if expr.has(symx) and expr.has(symy):
                expr_cishu = []
                for arg in expr.args:
                    if arg.has(symx) and not arg.has(symy):
                        symx_degree = degree(arg, gen=symx)
                        expr_cishu.append(symx_degree)
                    elif not arg.has(symx) and arg.has(symy):
                        symy_degree = degree(arg, gen=symy)
                        expr_cishu.append(symy_degree)
                    elif arg.has(symx) and arg.has(symy):
                        symx_degree = degree(arg, gen=symx)
                        symy_degree = degree(arg, gen=symy)
                        expr_cishu.append(symx_degree + symy_degree)
                cishu = max(expr_cishu)
                if cishu == 2:
                    answer = True
                    self.steps.append(["", "由二元二次方程的定义知，方程%s是二元二次方程" % (BaseEq(eq).printing())])
                else:
                    self.steps.append(["", "由二元二次方程的定义知，方程%s不是二元二次方程" % (BaseEq(eq).printing())])
            else:
                self.steps.append(["", "由二元二次方程的定义知，方程%s不是二元二次方程" % (BaseEq(eq).printing())])
        elif expr.has(symx) and expr.has(symy):
            symx_degree = degree(expr, gen=symx)
            symy_degree = degree(expr, gen=symy)
            expr_cishu = symx_degree + symy_degree
            if expr_cishu == 2:
                answer = True
                self.steps.append(["", "由二元二次方程的定义知，方程%s是二元二次方程" %
                                   (BaseEq(eq).printing())])
            else:
                self.steps.append(["", "由二元二次方程的定义知，方程%s不是二元二次方程" %
                                   (BaseEq(eq).printing())])
        else:
            self.steps.append(["", "由二元二次方程的定义知，方程%s不是二元二次方程" %
                               (BaseEq(eq).printing())])
        self.output.append(BaseVariable(answer))
        self.label.add("判断方程是否是二元二次方程")
        return self


# 二元二次方程的系数：Ax^2+By^2+Cxy+Dx+Ey+F=0 ==> A,B,C,D,E,F
class ErYuanErCiCoeff(BaseFunction):
    def solver(self, *args):
        eq = args[0].sympify()
        expr = (eq[0] - eq[1]).expand().simplify().expand()
        symx, symy = default_symbols(expr)
        da = expr.coeff(symx ** 2)
        db = expr.coeff(symy ** 2)
        dc = expr.coeff(symx * symy)
        dd = expr.coeff(symx)
        de = expr.coeff(symy)
        a1 = common_opers.expr_symb_terms_and_others(expr, symx)
        a2 = common_opers.expr_symb_terms_and_others(a1[1], symy)
        df = a2[1]
        self.steps.append(["", "该二元二次方程的各项系数为%s" % (BaseValues([da, db, dc, dd, de, df]).printing())])
        self.output.append(BaseValues([da, db, dc, dd, de, df]))
        self.label.add("求二元二次方程的系数")
        return self


# 判断二元一次方程是否是圆
class YuanJudge(BaseFunction):
    def solver(self, *args):
        answer = False
        answer_eryuanerci = ErYuanErCiJudge().solver(args[0]).output[0].sympify()
        if answer_eryuanerci:
            da, db, dc, dd, de, df = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
            if da == db and dc == 0:
                panbieshi = (dd / da) ** 2 + (de / da) ** 2 - 4 * (df / da)
                if panbieshi > 0:
                    answer = True
                    self.steps.append(["", "由圆方程的定义知，该二元一次方程是圆的方程。"])
        else:
            self.steps.append(["", "由圆方程的定义知，该二元一次方程不是圆的方程。"])
        self.output.append(BaseVariable(answer))
        self.label.add("判断二元一次方程是否是圆")
        return self


# 二元二次方程表示圆，求参
class YuanDingYi(BaseFunction):
    """
    已知方程x^{2}+y^{2}-2(t+3)x+2(1-4t^{2})y+16t^{4}+9=0表示一个圆,求t的取值范围
    """
    def solver(self, *args):
        yuan = args[0].sympify()
        expr = simplify(yuan[0] - yuan[1])
        symx, symy = default_symbols(expr)
        symx_expr = S.Zero
        symy_expr = S.Zero
        constant_expr = S.Zero
        for arg in expr.args:
            arg_symbols = arg.free_symbols
            if (symx in arg_symbols) and (symy not in arg_symbols):
                symx_expr += arg
            if (symy in arg_symbols) and (symx not in arg_symbols):
                symy_expr += arg
            if (symx not in arg_symbols) and (symy not in arg_symbols):
                constant_expr += arg
        remain_expr = expr - symx_expr - symy_expr - constant_expr
        if not remain_expr:
            if degree(symx_expr, gen=symx) == 2 and degree(symy_expr, gen=symy) == 2:
                symxx_coeff = symx_expr.coeff(symx ** 2)
                symyy_coeff = symy_expr.coeff(symy ** 2)
                if symxx_coeff == symyy_coeff:
                    dd = symx_expr.coeff(symx) / symxx_coeff
                    de = symy_expr.coeff(symy) / symxx_coeff
                    df = constant_expr / symxx_coeff
                    panbieshi = dd ** 2 + de ** 2 - 4 * df
                    eqs = [panbieshi, ">", S.Zero]
                    self.steps.append(["依题意，得", BaseIneq(eqs).printing()])
                    self.output.append(BaseIneq(eqs))
        self.label.add("二元二次方程表示圆，求参")
        return self


# 求圆的一般式
class GetYuanGeneralizedEq(BaseFunction):
    """
    圆x^{2}+y^{2}=1与直线2x+3y-2=0的位置关系是()
    """
    def solver(self, *args):
        if len(args) == 1 and isinstance(args[0], (BaseYuanName, BasePointName, BaseVariable)):
            name = args[0].value
            yuan = self.search(name)
        else:
            name = ""
            yuan = args[0]
        yibanshi = Yuan(yuan).generalizedEq.sympify()
        self.output.append(BaseYuan({"name": name, "value": [yibanshi[0], yibanshi[1]]}))
        # self.label.add("求圆的一般式")
        return self


# 求圆的标准方程
class GetYuanNormalizedEq(BaseFunction):
    """
    直线x-\\sqrt{3}y+2=0被圆x^{2}+y^{2}=4截得的弦长为()
    """
    def solver(self, *args):
        yibanshi = args[0].sympify()
        expr = yibanshi[0] - yibanshi[1]
        symx, symy = default_symbols(expr)
        symx_expr = S.Zero
        symy_expr = S.Zero
        constant_expr = S.Zero
        for arg in expr.args:
            arg_symbols = arg.free_symbols
            if (symx in arg_symbols) and (symy not in arg_symbols):
                symx_expr += arg
            if (symy in arg_symbols) and (symx not in arg_symbols):
                symy_expr += arg
            if (symx not in arg_symbols) and (symy not in arg_symbols):
                constant_expr += arg
        new_symx_expr = peifang(symx_expr, symx)
        da = symx_expr.coeff(symx ** 2)
        ex = new_symx_expr
        ex_cont = S.Zero
        if ex.is_Add:
            ex_cont, ex = ex.as_independent(symx)
        new_symy_expr = peifang(symy_expr, symy)
        ey = new_symy_expr
        ey_cont = S.Zero
        if ey.is_Add:
            ey_cont, ey = ey.as_independent(symy)
        new_constant = -(ex_cont + ey_cont + constant_expr)
        yuan = BaseYuan({"name": "", "value": [ex / da + ey / da, new_constant / da]})
        # self.steps.append(["","配方得"])
        # self.steps.append(["","%s" % yuan.txt.printing()])
        self.output.append(yuan)
        # self.label.add("求圆的标准方程")
        return self


# 求圆的圆心
class GetYuanCenterPoint(BaseFunction):
    """
    直线x-\\sqrt{3}y+2=0被圆x^{2}+y^{2}=4截得的弦长为()
    """
    def solver(self, *args):
        yuanxin = Yuan(args[0]).centerPoint.sympify()
        name = args[0].name
        self.steps.append(["", "圆的圆心为%s" % (
            BasePoint({"name": "", "value": [yuanxin[0], yuanxin[1]]}).printing())])
        self.output.append(BasePoint({"name": name, "value": [yuanxin[0], yuanxin[1]]}))
        self.label.add("求圆的圆心")
        return self


# 求圆的半径
class GetYuanRadius(BaseFunction):
    """
    直线x-\\sqrt{3}y+2=0被圆x^{2}+y^{2}=4截得的弦长为()
    """
    def solver(self, *args):
        banjing = Yuan(args[0]).radius.sympify()
        self.steps.append(["", "圆的半径为 %s" % (new_latex(banjing))])
        self.output.append(BasePoly(banjing))
        self.label.add("求圆的半径")
        return self


# 求圆的面积
class GetYuanArea(BaseFunction):
    """
    圆x^{2}+y^{2}+4x+3=0的面积是().
    """
    def solver(self, *args):
        banjing = args[0].sympify()
        mianji = pi * banjing * banjing
        self.steps.append(["", "∴ 圆的面积为%s" % (new_latex(mianji))])
        self.output.append(BasePoly(mianji))
        self.label.add("求圆的面积")
        return self


# 求圆的周长
class GetYuanPerimeter(BaseFunction):
    """
    圆x^{2}+y^{2}-2x+2y=0的周长是()
    """
    def solver(self, *args):
        banjing = args[0].sympify()
        zhouchang = 2 * pi * banjing
        self.steps.append(["", "∴ 圆的周长为%s" % (new_latex(zhouchang))])
        self.output.append(BasePoly(zhouchang))
        self.label.add("求圆的周长")
        return self


# 求圆的直径
class GetYuanDiameter(BaseFunction):
    def solver(self, *args):
        banjing = args[0].sympify()
        zhijing = 2 * banjing
        self.steps.append(["", "∴ 圆的直径为%s" % (new_latex(zhijing))])
        self.output.append(BasePoly(zhijing))
        self.label.add("求圆的直径")
        return self


if __name__ == '__main__':
    pass
